home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / pluginy Firefox / 8538 / 8538.xpi / content / boot / scripts / boot.js next >
Text File  |  2010-02-06  |  16KB  |  555 lines

  1. // This file contains the minimum set of scripts needed to boot Feedly. By boot we mean start, check version, if necessary
  2. // download and expand app and load the application. It is important to keep the boot to the very minimum because
  3. // we can not auto-update the boot.
  4.  
  5. // ---------------------------------------------------------------------------------------------
  6. // OBSERVABLE
  7. // ---------------------------------------------------------------------------------------------
  8. function createObservable( id )
  9. {
  10.     // private variables and methods ----------------------------
  11.     var fObservers = []
  12.  
  13.     // public interface -----------------------------------------
  14.     var that = {};
  15.     that.id  = id;
  16.     
  17.     that.registerObserver = function( obsObj )
  18.     {
  19.         if (fObservers.indexOf(obsObj) >= 0) {
  20.             return 
  21.         }
  22.         // BDH: that.$debug( "Registering observer for:" + id + " has " + fObservers.length + " observers. Hint: " +  obsObj.id );
  23.         fObservers.push(obsObj)
  24.     } 
  25.     
  26.     that.unregisterObserver = function( obsObj )
  27.     {
  28.         ///D that.$debug( "unregistering observer for:" +  that.id + " -- channel: " + getChannelId(obsObj) );
  29.         var idx = fObservers.indexOf(obsObj)
  30.         if (idx < 0) {
  31.             return
  32.         }
  33.         fObservers.splice(idx,1)
  34.     }
  35.     
  36.     that.removeAllObservers = function () 
  37.     {
  38.         fObservers = []
  39.     }
  40.  
  41.     that.fire = function ( aspect,a1,a2,a3,a4,a5,a6,a7,a8 )   // , arg1 , ..., argN
  42.     {
  43.         // Are there any observers?
  44.         if( fObservers.length == 0 ) {
  45.             return
  46.         }
  47.         // copy list of observers, so we don't mutate while we loop
  48.         var observers = new Array()
  49.         for(var oI in fObservers) {
  50.             observers.push ( fObservers [oI] )
  51.         }
  52.  
  53.         // The observer list may change as it fire notifications. Make sure that
  54.         // we take this into account
  55.         // Iterate through list of observers
  56.         for( var i=0;  i < observers.length; i++ ) 
  57.         {
  58.             try
  59.             {
  60.                 // Notify each observer
  61.                 var obs = observers[i]
  62.                 
  63.                 if (fObservers.indexOf(obs) < 0) {
  64.                     continue
  65.                 }
  66.              
  67.                 // 1. check if the aspect is a property of observer
  68.                 if( obs[aspect] != null ) 
  69.                 {
  70.                     // Call this method; here we don't pass aspect
  71.                     obs[aspect].call (obs,a1,a2,a3,a4,a5,a6,a7,a8);
  72.                     continue;
  73.                 }  
  74.         
  75.                 // 2. check generic onEvent method
  76.                 if (obs.onEvent != null) 
  77.                 {
  78.                     // generic aspect: 'onChanged'
  79.                     obs.onChanged.call ( obs, aspect,a1,a2,a3,a4,a5,a6,a7,a8 )
  80.                     continue;
  81.                 }
  82.                 // 3. It's a function 
  83.                 if ( typeof( obs ) == "function" ) 
  84.                 {
  85.                     obs.call ( obs, aspect,a1,a2,a3,a4,a5,a6,a7,a8 )
  86.                     continue;
  87.                 }
  88.             }
  89.             catch( e )
  90.             {
  91.                 // ignore
  92.                 that.$debug( devhd.utils.ExceptionUtils.formatError( "notify observer", e ) + ". Hint about observer:" + observers[ i ].id + "." + aspect );
  93.                 // that.unregisterObserver( observers[i] );
  94.             }
  95.         }
  96.         // done
  97.     };    
  98.     
  99.     that.toString = function () 
  100.     {
  101.         return "[service:" + this.id + "]"
  102.     }
  103.     
  104.     that.$debug = function (msg) 
  105.     {
  106.         $debug( "[" + this.id + "] " + msg)
  107.     }    
  108.     return that;
  109. };
  110.  
  111.  
  112. function createNetworkStack( id )
  113. {
  114.     var HTTP_MAX_TIMEOUT = 60 * 1000; // 60 seconds
  115.  
  116.     var that = createObservable (id)
  117.     
  118.     /////////////////////////////////////////////////
  119.     // HTTP/XML COMMUNICATION FACILITIES
  120.     /////////////////////////////////////////////////    
  121.     that.get = function( url, onCompleteFunction, onErrorFunction, contentType )
  122.     {
  123.         var timeoutTimer = null;
  124.         
  125.         function onCompleteHandler()
  126.         {
  127.             try
  128.             {
  129.                 ///D that.$debug( "get completed:" + request.status )
  130.                 
  131.                 // has this request already timed out? 
  132.                 if( timeoutTimer == null )
  133.                     return; // if so there is nothing to be done
  134.                     
  135.                 // cancel timeout timer
  136.                 that.clearTimeout( timeoutTimer );
  137.                 timeoutTimer = null;
  138.  
  139.                 if( request.status < 200 || request.status >=300 )
  140.                 {
  141.                     onErrorFunction.call( this, request.status, request.statusMessage );    
  142.                 }
  143.                 else
  144.                 {
  145.                     if( contentType == "text/xml" )
  146.                     {
  147.                         var responseXML = request.responseXML;
  148.                         onCompleteFunction.call( this, responseXML );
  149.                         
  150.                     }
  151.                     else
  152.                     {
  153.                         var responseText = request.responseText;
  154.                         
  155.                         // try to see if there is a "data-version" header associated with the response
  156.                         var dataVersion = request.getResponseHeader( "data-version" );
  157.                         
  158.                         onCompleteFunction.call( this, responseText, dataVersion );
  159.                     }
  160.                 }
  161.             }
  162.             catch( e )
  163.             {
  164.                 that.$debug( "Javascript exception while completing get:" + e.name + " - " + e.message + " -- " + e.fileName + " -- " + e.lineNumber )
  165.                 onErrorFunction.call( this, -1, "Javascript Exception: " + e.name + " - " + e.message );    
  166.             }
  167.         }
  168.  
  169.         function onErrorHandler()
  170.         {
  171.             ///D that.$debug( "get onErrorHandler:"  + url + " -- " + timeoutTimer );
  172.  
  173.             // has this request already timed out? 
  174.             if( timeoutTimer == null )
  175.                 return; // if so there is nothing to be done
  176.                 
  177.             // cancel timeout timer
  178.             that.clearTimeout( timeoutTimer );
  179.             timeoutTimer = null;
  180.             
  181.             var stat, statMsg;
  182.             
  183.             try
  184.             {
  185.                 stat = request.status;
  186.                 statMsg = request.statusMessage;
  187.             }
  188.             catch( e )
  189.             {
  190.                 stat = -3;
  191.                 statMsg = "data unavailable";
  192.             }
  193.             
  194.             onErrorFunction.call( this, stat, statMsg );    
  195.         }
  196.  
  197.         try
  198.         {
  199.             var request = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance();
  200.             
  201.             // QI the object to nsIDOMEventTarget to set event handlers on it:
  202.             request.QueryInterface(Components.interfaces.nsIDOMEventTarget);
  203.             request.addEventListener( "load",  onCompleteHandler,  false );
  204.             request.addEventListener( "error", onErrorHandler, false );
  205.  
  206.             // QI it to nsIXMLHttpRequest to open and send the request:
  207.             request.QueryInterface(Components.interfaces.nsIXMLHttpRequest);
  208.             request.open("GET", url, true);
  209.             request.send(null); 
  210.  
  211.             // set a timeout of 30 seconds
  212.             timeoutTimer = that.setTimeout( function()
  213.                                             {
  214.                                                 timeoutTimer = null;
  215.                                                 onErrorFunction.call( this, -2, "request timedout" );    
  216.                                             },
  217.                                             HTTP_MAX_TIMEOUT
  218.                                             );
  219.         }
  220.         catch( e )
  221.         {
  222.             that.$debug( "Javascript exception while executing get:" + e.name + " - " + e.message )
  223.             onErrorFunction.call( this, -1, "Javascript Exception: " + e.name + " - " + e.message );                
  224.         }        
  225.     }
  226.  
  227.  
  228.     ///////////////////////////////////////////////////////////////////////////////////////////////////
  229.     // Streets Timer Facility
  230.     ///////////////////////////////////////////////////////////////////////////////////////////////////
  231.     var nextTimerID = 1
  232.     var timers = {}
  233.     
  234.     function addTimer ( aTimer, kind ) 
  235.     {
  236.         var id = kind + nextTimerID++
  237.         timers [ id ] = aTimer
  238.         // that.$debug("added " + id)
  239.         return id
  240.     }
  241.     
  242.     function clearTimer ( id ) 
  243.     {
  244.         var t = timers [id]
  245.         if (t) {
  246.             t.cancel()
  247.             delete timers[id]
  248.             // that.$debug("cleared " + id)
  249.             return true
  250.         }
  251.         return false
  252.     }
  253.         
  254.     var Timer = Components.classes["@mozilla.org/timer;1"];
  255.     var nsITimer = Components.interfaces.nsITimer;
  256.     
  257.     that.setTimeout = function( callbackFunc, delay )
  258.     {
  259.         var aTimer = Timer.createInstance(nsITimer);
  260.         var timerId = addTimer(aTimer,"timeout.oneshot.")    
  261.         aTimer.init( { observe: function() {
  262.                                     clearTimer (timerId)
  263.                                     callbackFunc.call( this );
  264.                                 }
  265.                      },
  266.                     delay, 
  267.                     nsITimer.TYPE_ONE_SHOT 
  268.                     );
  269.                     
  270.         return timerId;
  271.     }
  272.     
  273.     that.clearTimeout = function( id )
  274.     {
  275.         return clearTimer( id );
  276.     }
  277.     
  278.     that.setInterval = function( callbackFunc, delay )
  279.     {
  280.         var aTimer = Timer.createInstance(nsITimer);
  281.         var timerId = addTimer ( aTimer,"interval.slack." )
  282.         
  283.         aTimer.init( { observe: function()
  284.                                 {
  285.                                     callbackFunc.call( this );
  286.                                } }, 
  287.                     delay, 
  288.                     nsITimer.TYPE_REPEATING_SLACK 
  289.                     );                
  290.         return timerId;
  291.     }
  292.     
  293.     that.clearInterval = function( id )
  294.     {
  295.         return clearTimer( id );
  296.     }
  297.  
  298.     that.setCookieString = function( uri, cookieString )
  299.     {
  300.         var cookieManager = Components.classes["@mozilla.org/cookiemanager;1"]
  301.                                       .getService( Components.interfaces.nsICookieManager );
  302.  
  303.         var ioService = Components.classes["@mozilla.org/network/io-service;1"]
  304.                                       .getService(Components.interfaces.nsIIOService);
  305.  
  306.            var cookieService = Components.classes["@mozilla.org/cookieService;1"]
  307.                                       .getService(Components.interfaces.nsICookieService);      
  308.         
  309.         if( ioService == null || cookieManager == null )
  310.             return;
  311.  
  312.         var cookieURI = ioService.newURI( uri, null, null);
  313.  
  314.            cookieService.setCookieString( cookieURI, null, cookieString , null);        
  315.     }
  316.  
  317.     ///////////////////////////////////////////////////////////////////////////////////////////////////
  318.     // Content download capabilities
  319.     ///////////////////////////////////////////////////////////////////////////////////////////////////
  320.     
  321.     /** 
  322.      * The download listener.
  323.      * 
  324.      * @param {Object} completeFunc
  325.      * @param {Object} errorFunc
  326.      */
  327.     
  328.     function Downloader (persist, httpChannel, completeFunc, errorFunc ) {        
  329.         this.persist = persist
  330.         this.persist.progressListener = this
  331.         this.httpChannel = httpChannel
  332.         this.completeFunc = completeFunc
  333.         this.errorFunc = errorFunc;
  334.     }
  335.     
  336.     Downloader.prototype = {
  337.         saveTo: function ( localURI ) {
  338.             this.persist.saveChannel(this.httpChannel,localURI);        
  339.         },
  340.         cancelSave: function () {
  341.             this.persist.cancelSave();
  342.         },
  343.         setTimeoutTimer: function (aTimer) {
  344.             this.aTimer = aTimer
  345.         },
  346.         QueryInterface: function(aIID)
  347.         {
  348.             if( aIID.equals(Components.interfaces.nsIWebProgressListener) ||
  349.                 aIID.equals(Components.interfaces.nsISupportsWeakReference) ||
  350.                 aIID.equals(Components.interfaces.nsISupports))
  351.                 return this;
  352.             throw Components.results.NS_NOINTERFACE;
  353.         },
  354.         onLocationChange: function (webProgress , request , location ) 
  355.         {    
  356.         },
  357.         onProgressChange: function ( webProgress , request , curSelfProgress , maxSelfProgress, curTotalProgress, maxTotalProgress ) 
  358.         {
  359.         },
  360.         onSecurityChange: function ( webProgress , request , state )
  361.         {
  362.         },
  363.         onStatusChange: function (webProgress, request, status, message )
  364.         {
  365.         },
  366.         onStateChange: function(aProgress, aRequest, aFlag, aStatus)
  367.         {
  368.             if(aFlag & Components.interfaces.nsIWebProgressListener.STATE_START)
  369.             {
  370.                 that.$debug("Start download of " + this.httpChannel.URI.spec)
  371.             } 
  372.             else if (aFlag & Components.interfaces.nsIWebProgressListener.STATE_STOP)
  373.             {
  374.                 var majorStatus = 0, status = 0
  375.                 // if stats != 0, then we don't have http status anyway
  376.                 if (aStatus == 0) {
  377.                     status = this.httpChannel.responseStatus
  378.                     majorStatus = Math.floor(status/100)
  379.                 }
  380.                 clearTimer ( this.aTimer );
  381.                     
  382.                 that.$debug("Finished download of " + this.httpChannel.URI.spec + " [" + status + "," +  aStatus.toString(16) + "]")
  383.                 
  384.                 if ( (majorStatus == 2 || majorStatus == 3) && aStatus == 0) {
  385.                     if (this.completeFunc) {
  386.                         that.setTimeout(this.completeFunc,0)                    
  387.                     }
  388.                 } else {
  389.                     if (this.errorFunc) {
  390.                         that.setTimeout(this.errorFunc,0);                    
  391.                     }
  392.                 }
  393.             }
  394.         }
  395.     }
  396.  
  397.     /**    
  398.      * The actual download hook.
  399.      * @param {Object} remoteLocation
  400.      * @param {Object} localLocation
  401.      * @param {Object} onComplete
  402.      * @param {Object} onError
  403.      */
  404.     that.download  = function( remoteLocation, localLocation, onComplete, onError )
  405.     {
  406.         var ioService = Components.classes["@mozilla.org/network/io-service;1"].getService(Components.interfaces.nsIIOService);
  407.          var persist = Components.classes['@mozilla.org/embedding/browser/nsWebBrowserPersist;1']
  408.                                   .createInstance(Components.interfaces.nsIWebBrowserPersist);
  409.   
  410.         persist.persistFlags = Components.interfaces.nsIWebBrowserPersist.PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION 
  411.                              | Components.interfaces.nsIWebBrowserPersist.PERSIST_FLAGS_REPLACE_EXISTING_FILES 
  412.                              | Components.interfaces.nsIWebBrowserPersist.PERSIST_FLAGS_BYPASS_CACHE ;
  413.         
  414.          var remoteURI = ioService.newURI(remoteLocation, null, null);
  415.         var localURI = ioService.newURI(localLocation, null, null);
  416.         var channel = ioService.newChannelFromURI( remoteURI );
  417.         
  418.         var downloader = new Downloader ( persist, channel.QueryInterface(Components.interfaces.nsIHttpChannel),
  419.                                           onComplete , onError )
  420.         // note: for some reason doing this from inside the callbacks in the 
  421.         //       Downloader does not work - the http channel always aborts !!
  422.         downloader.setTimeoutTimer( that.setTimeout(function() { downloader.cancelSave() },HTTP_MAX_TIMEOUT ) )
  423.         // start it
  424.         downloader.saveTo( localURI )
  425.         // this way you can save cancelSave
  426.         return downloader;
  427.     }
  428.     
  429.  
  430. // File helper
  431.     var PERMS_DIRECTORY = 0755;
  432.         
  433.     that.getFile = function( path, relativePath )
  434.     {
  435.         var obj = Components.classes["@mozilla.org/file/local;1"].
  436.         createInstance(Components.interfaces.nsILocalFile);
  437.         obj.initWithPath( path );
  438.         if( relativePath != null )
  439.         {
  440.             var parts = relativePath.split( "/" );
  441.             for( var i = 0; i < parts.length; i++ )
  442.                 obj.append( parts[ i ] );
  443.         }
  444.         
  445.         if( obj.exists() == false )
  446.             obj.create( Components.interfaces.nsILocalFile.NORMAL_FILE_TYPE, PERMS_DIRECTORY ); 
  447.         
  448.         return obj;
  449.     }
  450.  
  451.  
  452.  
  453.     that.getDir = function( path, relativePath )
  454.     {
  455.         var obj = Components.classes["@mozilla.org/file/local;1"].
  456.         createInstance(Components.interfaces.nsILocalFile);
  457.         obj.initWithPath( path );
  458.         if( relativePath != null )
  459.         {
  460.             var parts = relativePath.split( "/" );
  461.             for( var i = 0; i < parts.length; i++ )
  462.                 obj.append( parts[ i ] );
  463.         }
  464.         
  465.         if( obj.exists() == false )
  466.             obj.create( Components.interfaces.nsILocalFile.DIRECTORY_TYPE, PERMS_DIRECTORY ); 
  467.         
  468.         return obj;
  469.     }
  470.  
  471.     that.removeDir = function( path, relativePath )
  472.     {
  473.         var obj = Components.classes["@mozilla.org/file/local;1"].
  474.         createInstance(Components.interfaces.nsILocalFile);
  475.         obj.initWithPath( path );
  476.         if( relativePath != null )
  477.         {
  478.             var parts = relativePath.split( "/" );
  479.             for( var i = 0; i < parts.length; i++ )
  480.                 obj.append( parts[ i ] );
  481.         }
  482.         
  483.         if( obj.exists() == true )
  484.             obj.remove( true );
  485.     }
  486.  
  487.     
  488.     that.extractZipFile = function( zipFile, targetLocation )
  489.     {
  490.         ///D that.$debug( "received request to extract zip file into: " + targetLocation );
  491.         
  492.         var zipReader = Components.classes["@mozilla.org/libjar/zip-reader;1"]
  493.                                   .createInstance(Components.interfaces.nsIZipReader);
  494.         
  495.         if( zipReader.init != null ) // FF2
  496.         {
  497.             zipReader.init( zipFile );
  498.             zipReader.open();
  499.             
  500.             // create directories first
  501.               var entries = zipReader.findEntries("*/");
  502.               while (entries.hasMoreElements())
  503.             {
  504.                 var entry = entries.getNext().QueryInterface(Components.interfaces.nsIZipEntry);
  505.                 
  506.                 // getDir will create the directory if it does not exist
  507.                 var target = that.getDir( targetLocation, entry.name );
  508.               }
  509.             
  510.             entries = zipReader.findEntries( "*" );
  511.             while( entries.hasMoreElements() ) 
  512.             {
  513.                 var entry = entries.getNext().QueryInterface( Components.interfaces.nsIZipEntry );            
  514.     
  515.                 var entryName = new String( entry.name );
  516.                 if( entryName.lastIndexOf( "/" ) == entryName.length - 1 )
  517.                     continue; // skip directories
  518.     
  519.                 var targetFile = that.getFile( targetLocation, entry.name );
  520.                 zipReader.extract(entry.name, targetFile);
  521.             }
  522.             zipReader.close();            
  523.         }
  524.         else //FF3
  525.         {
  526.             zipReader.open( zipFile );
  527.             
  528.             // create directories first
  529.               var entryNames = zipReader.findEntries("*/");
  530.               while (entryNames.hasMore())
  531.             {
  532.                 // getDir will create the directory if it does not exist
  533.                 var target = that.getDir( targetLocation, entryNames.getNext() );
  534.               }
  535.             
  536.             entryNames = zipReader.findEntries( "*" );
  537.             while( entryNames.hasMore() ) 
  538.             {
  539.                 var entryName = entryNames.getNext();            
  540.     
  541.                 if( entryName.lastIndexOf( "/" ) == entryName.length - 1 )
  542.                     continue; // skip directories
  543.     
  544.                 var targetFile = that.getFile( targetLocation, entryName );
  545.                 zipReader.extract( entryName, targetFile);
  546.             }
  547.             zipReader.close();            
  548.         }
  549.     }
  550.     
  551.     //
  552.     return that;
  553. }
  554.  
  555.